<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<script type="text/javascript">
			//创建Object实例，为它添加属性和方法
					var person = new Object();
					person.name = "ls";
					person.age = 24;
					person.job = "前端工程师";
					person.sayName = function(){
						alert(this.name);
					}
			
			//对象字面量
					var person = {
						name:"ls",
						age:24,
						job:"前端工程师",
						sayName:function(){
							alert(this.name);
						}
					}
		            for(var i in person){
		            	console.log(i);
		            }
            //1.数据属性 
              //数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有 4个描述其行为的特性
              //[[Configurable]]：表示能否通过 delete 删除属性从而重新定义属性，能否修改属性的特性，或者能否把属性修改为访问器属性。
              //[[Enumerable]]：表示能否通过 for-in 循环返回属性。像前面例子中那样直接在对象上定义的属性，它们的这个特性默认值为 true。
              //[[Writable]]：表示能否修改属性的值。像前面例子中那样直接在对象上定义的属性，它们的这个特性默认值为 true。
              //[[Value]]：包含这个属性的数据值。读取属性值的时候，从这个位置读；写入属性值的时候，把新值保存在这个位置。这个特性的默认值为 undefined。
              
             //修改属性默认的特性，必须使用 ECMAScript 5 的 Object.defineProperty()方法。
             //这个方法接收三个参数：属性所在的对象、属性的名字和一个描述符对象。
             //其中，描述符（descriptor）对象的属性必须是：configurable、enumerable、writable 和 value。
						var person = {};
						Object.defineProperty(person,'name',{
							writable:false,//false表示这个属性的值不可修改
							name:'ls'
						});
						console.log(person.name);//
						person.name = 'lishan';//非严格模式下，赋值操作会被忽略；严格模式下，赋值擦偶作会抛出错误
						
						//类似的规则也适用于不可配置的属性
						var person = {};
						Object.defineProperty(person,'name',{
							configurable:false,
							value:'ls'
						});
						console.log(person.name);//ls
						delete person.name;
						console.log(person.name);//严格模式报错
						Object.defineProperty(person,'name',{
							configurable:false,
							value:'ls'
						});
						Object.defineProperty(person,'name',{
							//把属性定义为不可配置的，就不能再把它变回可配置了。
							//此时，再调用 Object.defineProperty()方法修改除 writable 之外的特性，都会导致错误
							//在调用 Object.defineProperty()方法时，如果不指定，configurable、enumerable 和writable 特性的默认值都是 false。
							configurable:true,
							value:'ls'
						});
						
          
            
            
            //2.访问器属性
               //访问器属性不包含数据值；它们包含一对儿 getter 和 setter 函数（不过，这两个函数都不是必需的）。
               //在读取访问器属性时，会调用getter 函数，这个函数负责返回有效的值
               //在写入访问器属性时，会调用setter 函数并传入新值，这个函数负责决定如何处理数据
                
               //访问器属性有如下 4 个特性
               //[[Configurable]]：表示能否通过 delete 删除属性从而重新定义属性，能否修改属性的特性，或者能否把属性修改为数据属性。
               //[[Enumerable]]：表示能否通过 for-in 循环返回属性。对于直接在对象上定义的属性，这个特性的默认值为 true。
               //[[Get]]：在读取属性时调用的函数。默认值为 undefined。
               //[[Set]]：在写入属性时调用的函数。默认值为 undefined。
               
               //访问器属性不能直接定义，必须使用 Object.defineProperty()来定义
					            var book = {
									_year:2004,
									edition:1
								}
								Object.defineProperty(book,'year',{
									get:function(){
										return this._year
									},
									set:function(newValue){
										console.log(newValue);//'lishan'
										if(newValue==='lishan'){
											this.edition = 'ls'+ newValue
										}
									}
								})
								book.year = 'lishan';
								console.log(book.edition);//'lslishan'
					          
					          
			    //6.1.2 定义多个属性
			    //ECMAScript 5 又定义了一个 Object.defineProperties()方法，支持IE9+。利用这个方法可以通过描述符一次定义多个属性。
			    //这个方法接收两个对象参数：第一个对象是要添加和修改其属性的对象，第二个对象的属性与第一个对象中要添加或修改的属性一一对应
			                var book = {};
							Object.defineProperties(book,{
								_year:{
								    configurable:true,
								    writable:true,
								    enumerable:true,
									value:2004
								},
								edition:{
									configurable:true,
									enumerable:true,
									writable:true,
									value:1
								},
								year:{
									configurable:true,
									enumerable:true,
									get:function(){
										return this._year
									},
									set:function(newValue){
										if(newValue > 2004){
											this._year = newValue;
											this.edition += newValue - 2004;
										}
									}
								}
							})
							book.year = 2005;
							console.log(book._year);//2005
							console.log(book.edition);//2
							for(var key in book){
								console.log(key);//_year edition year
							}
			    //6.1.3 读取属性的特性
			    //使用 ECMAScript 5 的 Object.getOwnPropertyDescriptor()方法，可以取得给定属性的描述符。
			   			var book = {};
						Object.defineProperties(book,{
							_year:{
								value:2004
							},
							edition:{
								value:1
							},
							year:{
								get:function(){
									return this._year
								},
								set:function(newValue){
									if(newValue > 2004){
										this._year = newValue;
										this.edition += newValue - 2004;
									}
								}
							}
						})
						var descriptor = Object.getOwnPropertyDescriptor(book,'_year');
						console.log(descriptor.configurable);//false
						console.log(descriptor.enumerable);//false
						console.log(descriptor.writable);//false
						console.log(descriptor.value);//2004
						console.log(descriptor.get);//undefined
						console.log(descriptor.set);//undefined
						var descriptor = Object.getOwnPropertyDescriptor(book,'year');
						console.log(descriptor.configurable);//false
						console.log(descriptor.enumerable);//false
						console.log(descriptor.writable);//undefined
						console.log(descriptor.value);//undefined
						console.log(descriptor.get);//function
						console.log(descriptor.set);//function
		</script>
	</body>
</html>
